/*
 * Copyright (c) 2006 Sun Microsystems, Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to 
 * deal in the Software without restriction, including without limitation the 
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
 * sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 **/

package com.iaroc.irobot.util;

import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.sensorboard.peripheral.LEDColor;

/**
 * simple utility to run some effects on the LEDs of the sensorboard
 * @author arshan
 * @author bob
 * @author David Mercier <david.mercier@sun.com>
 */
public class XLights {

	private LightRunner lightrunner = null;
	private ITriColorLED[] leds;
	private LEDColor myColor = LEDColor.YELLOW;
	private boolean on = true;
	private int speed = 70;
	private int indexFrom = 0;
	private int indexTo = 7;

	public XLights(EDemoBoard demo, int indexFrom, int indexTo) {
		this.leds = demo.getLEDs();
		this.indexFrom = indexFrom;
		this.indexTo = indexTo;
	}

	public void setColor(LEDColor clr ) {
	    boolean wasRunning = lightrunner != null;
	    stopPsilon();
		myColor = clr;
        for ( int x = indexFrom; x <= indexTo; x++) {
            leds[x].setColor(myColor);
        }
        if (wasRunning) {
            startPsilon();
        }
	}
	
	public void setDelay(int delayMs) {
		speed = delayMs;
	}

	public void lightsOn() {
		for ( int x = indexFrom; x <= indexTo; x++) {
		    leds[x].setColor(myColor);
			leds[x].setOn();
		}
	}

    public void displayCounts(int redCount, int greenCount, int blueCount) {
        final int intensity = 63;
        stopPsilon();
        int mask = 1;
        for (int i=0; i < leds.length; i++) {
            int r = (redCount & mask) ==0 ?0:intensity;
            int g = (greenCount & mask) ==0 ?0:intensity;
            int b = (blueCount & mask) ==0 ?0:intensity;
            leds[i].setOn();
            leds[i].setRGB(r, g, b);
            mask *= 2;
        }
    }
    
	public void setLED(int led, int r , int g, int b) {
		stopPsilon();
		leds[led].setRGB(r,g,b);
	}    

	public void startPsilon()  {
	    stopPsilon();
		lightsOn();
		lightrunner = new LightRunner();
		lightrunner.setPriority(Thread.MIN_PRIORITY);
		lightrunner.start();
	}

	public void stopPsilon() {

		if(lightrunner != null) {
			lightrunner.stopThread();
			try {
                lightrunner.join();
            } catch (InterruptedException e) {
            }
			lightrunner = null;
		}
	}

	private class LightRunner extends Thread {

		private boolean keepemrunning = true;

		public void stopThread() {
			keepemrunning = false;
		}

		private int reduce( int input ) {
			if ( input < 10 )
			    return 0;
			return input - ( input / 2 ) ;
		}

		private void decay() {
			for ( int x = indexFrom ; x <= indexTo ; x++ ) {
			    int r = reduce(leds[x].getRed());
			    int g = reduce(leds[x].getGreen());
			    int b = reduce(leds[x].getBlue());
				leds[x].setRGB(r, g, b);
			}
		}

		public void run() {
			int current = indexFrom;
			int trend = 1;

			boolean miserly = false;
			try {
				while (keepemrunning) {                    
					if ( on ) {
						if (miserly) {
							leds[indexFrom].setOn();
							leds[indexFrom].setColor(myColor);
							sleep(25);
							leds[indexFrom].setOff();
						} else {
							leds[current].setColor(myColor);
							decay();
                            current += trend;
							if (current < indexFrom || current > indexTo) {
							    trend  = -trend;
							    current += trend;
							}
						}
					} 
					Thread.sleep(speed);
				}
			} catch (Exception e ) {
				// so we dont run the lights, no sweat
			}
		}
	}   
}

